Een uitgebreide gids voor Content Security Policy (CSP) en andere frontend security headers, die webapplicaties beschermt tegen aanvallen en de gebruikersveiligheid wereldwijd verbetert.
Frontend Security Headers: Beheersen van Content Security Policy (CSP)
In het huidige digitale landschap, waar webapplicaties steeds complexer en meer onderling verbonden zijn, is bescherming tegen veiligheidsdreigingen van het grootste belang. Hoewel backend-beveiliging vaak veel aandacht krijgt, is frontend-beveiliging even cruciaal. Frontend security headers fungeren als de eerste verdedigingslinie en bieden een mechanisme om de browser te instrueren hoe zich te gedragen en gebruikers te beschermen tegen diverse aanvallen. Onder deze headers onderscheidt Content Security Policy (CSP) zich als een krachtig hulpmiddel om een breed scala aan risico's te beperken.
Wat zijn Frontend Security Headers?
Frontend security headers zijn HTTP-responseheaders die een webserver naar de browser stuurt. Deze headers bevatten instructies over hoe de browser de ontvangen content moet behandelen. Ze helpen veelvoorkomende aanvallen te voorkomen, zoals:
- Cross-Site Scripting (XSS): Het injecteren van kwaadaardige scripts in vertrouwde websites.
- Clickjacking: Gebruikers misleiden om op iets anders te klikken dan wat ze waarnemen.
- Man-in-the-Middle-aanvallen: Onderschepping van de communicatie tussen de gebruiker en de server.
Enkele van de belangrijkste frontend security headers zijn:
- Content Security Policy (CSP): Definieert de bronnen waarvandaan de browser resources mag laden.
- Strict-Transport-Security (HSTS): Dwingt de browser om HTTPS te gebruiken voor alle communicatie met de website.
- X-Frame-Options: Voorkomt dat de website wordt ingesloten in een iframe, wat clickjacking-aanvallen tegengaat.
- X-XSS-Protection: Schakelt de ingebouwde XSS-filter van de browser in. (Let op: Vaak vervangen door CSP, maar kan nog steeds een extra verdedigingslaag bieden).
- Referrer-Policy: Bepaalt de hoeveelheid referrer-informatie die met verzoeken wordt meegestuurd.
- Feature-Policy (nu Permissions-Policy): Stelt ontwikkelaars in staat om browserfuncties en API's selectief in en uit te schakelen.
Diepgaande Duik in Content Security Policy (CSP)
Content Security Policy (CSP) is een HTTP-responseheader die bepaalt welke resources de user agent mag laden voor een bepaalde pagina. Het whitelist in wezen bronnen van goedgekeurde content, waardoor het risico op XSS-aanvallen aanzienlijk wordt verminderd. Door expliciet de herkomst te definiëren van waaruit resources zoals scripts, stylesheets, afbeeldingen en lettertypen kunnen worden geladen, maakt CSP het voor aanvallers veel moeilijker om kwaadaardige code in uw website te injecteren.
Hoe CSP Werkt
CSP werkt door de browser een lijst te geven van goedgekeurde bronnen voor verschillende soorten content. Wanneer de browser een resource tegenkomt die de CSP schendt, blokkeert hij de resource en rapporteert de schending. Dit blokkeringsmechanisme voorkomt dat kwaadaardige code wordt uitgevoerd, zelfs als een aanvaller erin slaagt deze in de HTML te injecteren.
CSP-richtlijnen
CSP-richtlijnen (directives) zijn de kerncomponenten van een CSP-beleid. Ze specificeren de toegestane bronnen voor verschillende soorten resources. Enkele van de meest gebruikte richtlijnen zijn:
- default-src: Stelt de standaardbron in voor alle resourcetypen. Dit is een fallback-richtlijn die van toepassing is wanneer andere, meer specifieke richtlijnen niet zijn gedefinieerd.
- script-src: Specificeert de toegestane bronnen voor JavaScript.
- style-src: Specificeert de toegestane bronnen voor CSS-stylesheets.
- img-src: Specificeert de toegestane bronnen voor afbeeldingen.
- font-src: Specificeert de toegestane bronnen voor lettertypen.
- media-src: Specificeert de toegestane bronnen voor audio en video.
- object-src: Specificeert de toegestane bronnen voor plug-ins zoals Flash. (Over het algemeen het beste om plug-ins te vermijden indien mogelijk).
- frame-src: Specificeert de toegestane bronnen voor frames (iframes).
- connect-src: Specificeert de toegestane bronnen voor netwerkverzoeken (AJAX, WebSockets).
- base-uri: Beperkt de URL's die kunnen worden gebruikt in een
<base>-element. - form-action: Beperkt de URL's waarnaar formulieren kunnen worden verzonden.
- frame-ancestors: Specificeert geldige parents die een pagina mogen insluiten met
<frame>,<iframe>,<object>,<embed>, of<applet>. Deze richtlijn biedt bescherming tegen Clickjacking. - upgrade-insecure-requests: Instrueert user agents om alle onveilige URL's van een site (geladen via HTTP) te behandelen alsof ze zijn vervangen door veilige URL's (geladen via HTTPS). Deze richtlijn is bedoeld voor websites die bezig zijn met de migratie van HTTP naar HTTPS.
- report-uri: Specificeert een URL waarnaar de browser rapporten over CSP-schendingen moet sturen. Afgekeurd ten gunste van `report-to`.
- report-to: Specificeert een groepsnaam die is gedefinieerd in een `Report-To`-header. Dit maakt fijnmazigere controle over rapportage mogelijk, inclusief het specificeren van meerdere rapportage-eindpunten.
CSP-bronwaarden
Bronwaarden (source values) definiëren de herkomst van waaruit resources mogen worden geladen. Enkele veelvoorkomende bronwaarden zijn:
- *: Staat content van elke bron toe (Vermijd het gebruik hiervan in productie!).
- 'self': Staat content van dezelfde herkomst toe (schema, host en poort) als het beschermde document.
- 'none': Staat geen content van enige bron toe.
- 'unsafe-inline': Staat het gebruik van inline JavaScript en CSS toe (Vermijd het gebruik hiervan in productie!).
- 'unsafe-eval': Staat het gebruik van dynamische code-evaluatie toe (bijv.
eval(),Function()) (Vermijd het gebruik hiervan in productie!). - 'strict-dynamic': Specificeert dat het vertrouwen dat expliciet aan een script in de markup wordt gegeven, door het te vergezellen van een nonce of hash, wordt doorgegeven aan alle scripts die door die voorouder worden geladen.
- 'unsafe-hashes': Staat specifieke inline event handlers toe. Dit wordt over het algemeen afgeraden vanwege de complexiteit en het beperkte voordeel.
- data:: Staat het laden van resources van data-URL's toe (bijv. ingebedde afbeeldingen). Wees voorzichtig met het gebruik hiervan.
- mediastream:: Staat toe dat `mediastream:` URI's worden gebruikt als mediabron.
- blob:: Staat toe dat `blob:` URI's worden gebruikt als mediabron.
- filesystem:: Staat toe dat resources worden geladen vanaf een bestandssysteem.
- https://example.com: Staat content van een specifiek domein en poort toe.
- *.example.com: Staat content van elk subdomein van example.com toe.
- nonce-{random-value}: Staat scripts of stijlen toe met een overeenkomstig nonce-attribuut. Dit vereist server-side generatie van een willekeurige nonce-waarde voor elk verzoek.
- sha256-{hash-value}: Staat scripts of stijlen toe met een overeenkomstige SHA256-, SHA384- of SHA512-hash.
CSP-modi: Afdwingen vs. Alleen-Rapporteren
CSP kan in twee modi worden geïmplementeerd:
- Afdwingmodus (Enforce Mode): In deze modus blokkeert de browser alle resources die de CSP schenden. Dit is de aanbevolen modus voor productieomgevingen. De CSP wordt verzonden met de `Content-Security-Policy`-header.
- Alleen-Rapporteren-modus (Report-Only Mode): In deze modus rapporteert de browser CSP-schendingen maar blokkeert de resources niet. Dit is handig voor het testen en evalueren van een CSP voordat deze wordt afgedwongen. De CSP wordt verzonden met de `Content-Security-Policy-Report-Only`-header.
Implementeren van CSP: Een Stapsgewijze Gids
Het implementeren van CSP kan ontmoedigend lijken, maar door een gestructureerde aanpak te volgen, kunt u uw webapplicatie effectief beveiligen.
1. Begin met een Alleen-Rapporteren-beleid
Begin met het implementeren van een CSP in alleen-rapporteren-modus. Hiermee kunt u schendingen monitoren zonder de functionaliteit van uw website te verstoren. Configureer de report-uri- of report-to-richtlijn om schendingsrapporten naar een aangewezen eindpunt te sturen.
Voorbeeldheader (Alleen-Rapporteren):
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
2. Analyseer de Schendingsrapporten
Analyseer zorgvuldig de schendingsrapporten om te identificeren welke resources worden geblokkeerd en waarom. Dit helpt u de resource-afhankelijkheden van uw website te begrijpen en potentiële beveiligingskwetsbaarheden te identificeren.
Schendingsrapporten worden doorgaans als JSON-payloads verzonden naar het geconfigureerde report-uri- of report-to-eindpunt. Deze rapporten bevatten informatie over de schending, zoals de geblokkeerde URI, de geschonden richtlijn en de document-URI.
3. Verfijn het CSP-beleid
Op basis van de schendingsrapporten, verfijn uw CSP-beleid om legitieme resources toe te staan terwijl u een sterke beveiligingshouding handhaaft. Voeg specifieke bronwaarden toe voor de resources die worden geblokkeerd. Overweeg het gebruik van nonces of hashes voor inline scripts en stijlen om het gebruik van 'unsafe-inline' te vermijden.
4. Schakel over naar Afdwingmodus
Zodra u er zeker van bent dat uw CSP-beleid geen legitieme resources blokkeert, schakelt u over naar de afdwingmodus. Dit blokkeert alle resterende schendingen en biedt een robuuste beveiligingslaag tegen XSS-aanvallen.
Voorbeeldheader (Afdwingen):
Content-Security-Policy: default-src 'self'; script-src 'self' https://example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report
5. Monitor en Onderhoud het CSP-beleid
CSP is geen 'instellen en vergeten'-oplossing. Het is essentieel om uw CSP-beleid continu te monitoren en bij te werken naarmate uw website evolueert en er nieuwe beveiligingsdreigingen opduiken. Controleer regelmatig schendingsrapporten en pas het beleid indien nodig aan.
Praktische CSP-voorbeelden
Laten we enkele praktische CSP-voorbeelden bekijken voor verschillende scenario's:
Voorbeeld 1: Basis-CSP voor een Eenvoudige Website
Deze CSP staat content van dezelfde herkomst toe en staat afbeeldingen van elke bron toe.
Content-Security-Policy: default-src 'self'; img-src *
Voorbeeld 2: CSP met Specifieke Script- en Stijlbronnen
Deze CSP staat scripts toe van dezelfde herkomst en van een specifieke CDN, en stijlen van dezelfde herkomst en inline stijlen.
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'
Voorbeeld 3: CSP met Nonces voor Inline Scripts
Deze CSP vereist een unieke nonce voor elk inline script.
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0mn0nc3'
HTML:
<script nonce="r4nd0mn0nc3">console.log('Hello, world!');</script>
Belangrijk: De nonce-waarde moet voor elk verzoek dynamisch op de server worden gegenereerd. Dit voorkomt dat aanvallers de nonce hergebruiken.
Voorbeeld 4: CSP die Frame Ancestors Beperkt om Clickjacking te Voorkomen
Deze CSP voorkomt dat de pagina wordt ingesloten in een iframe op elk domein behalve `https://example.com`.
Content-Security-Policy: frame-ancestors 'self' https://example.com
Voorbeeld 5: Een strengere CSP met 'strict-dynamic' en een fallback naar 'self'
Deze CSP maakt gebruik van `strict-dynamic` voor moderne browsers, terwijl oudere browsers die dit niet ondersteunen nog steeds worden ondersteund. Het bevat ook een `report-uri` voor het monitoren van schendingen.
Content-Security-Policy: default-src 'self'; script-src 'strict-dynamic' 'nonce-{random-nonce}' 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report
Vergeet niet om `{random-nonce}` te vervangen door een dynamisch gegenereerde nonce-waarde aan de serverzijde.
CSP en Single-Page Applications (SPA's)
Het implementeren van CSP in SPA's kan een uitdaging zijn vanwege de dynamische aard van deze applicaties. SPA's vertrouwen vaak sterk op JavaScript om de DOM te genereren en te manipuleren, wat kan leiden tot CSP-schendingen als dit niet zorgvuldig wordt aangepakt.
Hier zijn enkele tips voor het implementeren van CSP in SPA's:
- Vermijd
'unsafe-inline'en'unsafe-eval': Deze richtlijnen moeten waar mogelijk worden vermeden in SPA's. Ze verzwakken de beveiliging van uw applicatie aanzienlijk. - Gebruik Nonces of Hashes: Gebruik nonces of hashes voor inline scripts en stijlen. Dit is de aanbevolen aanpak voor SPA's.
- Overweeg Trusted Types: Trusted Types is een browser-API die helpt bij het voorkomen van DOM-gebaseerde XSS-kwetsbaarheden. Het kan in combinatie met CSP worden gebruikt om de beveiliging verder te verbeteren.
- Gebruik een CSP-compatibel framework: Sommige frontend-frameworks (zoals React met specifieke configuraties, Angular en Vue.js) bieden functies om u te helpen CSP gemakkelijker te implementeren.
Andere Belangrijke Frontend Security Headers
Hoewel CSP een hoeksteen is van frontend-beveiliging, spelen andere headers een cruciale rol in het bieden van een uitgebreide verdedigingsstrategie:
Strict-Transport-Security (HSTS)
De Strict-Transport-Security (HSTS)-header instrueert de browser om altijd HTTPS te gebruiken om verbinding te maken met de website. Dit voorkomt man-in-the-middle-aanvallen die proberen de verbinding te downgraden naar HTTP.
Voorbeeldheader:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age: Specificeert de duur (in seconden) waarvoor de browser moet onthouden om de site alleen via HTTPS te benaderen. Een waarde van 31536000 seconden (1 jaar) wordt aanbevolen voor productieomgevingen.includeSubDomains: Geeft aan dat het HSTS-beleid van toepassing is op alle subdomeinen van het domein.preload: Stelt het domein in staat om te worden opgenomen in een lijst van HSTS-ingeschakelde domeinen die vooraf in browsers wordt geladen. Dit vereist dat u uw domein indient bij de HSTS-preloadlijst die door Google wordt onderhouden.
X-Frame-Options
De X-Frame-Options-header voorkomt clickjacking-aanvallen door te bepalen of de website in een iframe kan worden ingesloten.
Voorbeeldheader:
X-Frame-Options: DENY
Mogelijke waarden:
DENY: Voorkomt dat de pagina wordt weergegeven in een iframe, ongeacht de herkomst.SAMEORIGIN: Staat toe dat de pagina wordt weergegeven in een iframe alleen als de herkomst van het iframe overeenkomt met de herkomst van de pagina.ALLOW-FROM uri: Staat toe dat de pagina wordt weergegeven in een iframe alleen als de herkomst van het iframe overeenkomt met de opgegeven URI. Let op: Deze optie is verouderd en wordt mogelijk niet door alle browsers ondersteund.
Let op: De frame-ancestors-richtlijn in CSP biedt een flexibelere en krachtigere manier om framing te beheren en heeft over het algemeen de voorkeur boven X-Frame-Options.
X-XSS-Protection
De X-XSS-Protection-header schakelt de ingebouwde XSS-filter van de browser in. Hoewel CSP een robuustere oplossing is voor het voorkomen van XSS-aanvallen, kan deze header een extra verdedigingslaag bieden, vooral voor oudere browsers die CSP mogelijk niet volledig ondersteunen.
Voorbeeldheader:
X-XSS-Protection: 1; mode=block
1: Schakelt de XSS-filter in.0: Schakelt de XSS-filter uit.mode=block: Instrueert de browser om de pagina te blokkeren als een XSS-aanval wordt gedetecteerd.report=uri: Specificeert een URL waarnaar de browser een rapport moet sturen als een XSS-aanval wordt gedetecteerd.
Referrer-Policy
De Referrer-Policy-header bepaalt de hoeveelheid referrer-informatie die met verzoeken wordt meegestuurd. De referrer-informatie kan worden gebruikt om gebruikers over websites te volgen, dus het beheren ervan kan de privacy van gebruikers verbeteren.
Voorbeeldheader:
Referrer-Policy: strict-origin-when-cross-origin
Enkele veelvoorkomende waarden:
no-referrer: Stuur de Referer-header nooit.no-referrer-when-downgrade: Stuur de Referer-header niet naar origins zonder TLS (HTTPS).origin: Stuur alleen de herkomst (schema, host en poort) in de Referer-header.origin-when-cross-origin: Stuur de herkomst voor cross-origin-verzoeken en de volledige URL voor same-origin-verzoeken.same-origin: Stuur de Referer-header voor same-origin-verzoeken, maar niet voor cross-origin-verzoeken.strict-origin: Stuur alleen de herkomst wanneer het beveiligingsniveau van het protocol hetzelfde blijft (HTTPS naar HTTPS), maar stuur geen header naar een minder veilige bestemming (HTTPS naar HTTP).strict-origin-when-cross-origin: Stuur de herkomst bij een same-origin-verzoek. Stuur bij cross-origin-verzoeken de herkomst alleen als het beveiligingsniveau van het protocol hetzelfde blijft (HTTPS naar HTTPS), maar stuur geen header naar een minder veilige bestemming (HTTPS naar HTTP).unsafe-url: Stuur de volledige URL in de Referer-header, ongeacht de herkomst. Gebruik met uiterste voorzichtigheid, omdat dit gevoelige informatie kan blootleggen.
Permissions-Policy (voorheen Feature-Policy)
De Permissions-Policy-header (voorheen bekend als Feature-Policy) stelt ontwikkelaars in staat om browserfuncties en API's selectief in en uit te schakelen. Dit kan helpen het aanvalsoppervlak van uw applicatie te verkleinen en de privacy van gebruikers te verbeteren.
Voorbeeldheader:
Permissions-Policy: geolocation=()
Dit voorbeeld schakelt de geolocatie-API uit voor de website.
Andere functies die met Permissions-Policy kunnen worden beheerd, zijn onder meer:
cameramicrophonegeolocationaccelerometergyroscopemagnetometerusbmidipaymentfullscreen
Security Headers Instellen op Verschillende Platforms
De methode voor het instellen van security headers varieert afhankelijk van de webserver of het platform dat u gebruikt. Hier zijn enkele veelvoorkomende voorbeelden:
Apache
U kunt security headers in Apache instellen door ze toe te voegen aan het .htaccess-bestand of het serverconfiguratiebestand (httpd.conf).
Voorbeeld .htaccess-configuratie:
<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report"
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header set X-Frame-Options "DENY"
Header set X-XSS-Protection "1; mode=block"
Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
Nginx
U kunt security headers in Nginx instellen door ze toe te voegen aan het serverblok in het Nginx-configuratiebestand (nginx.conf).
Voorbeeld Nginx-configuratie:
server {
listen 443 ssl;
server_name example.com;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-Frame-Options "DENY";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
...
}
Node.js (Express)
U kunt security headers in Node.js instellen met middleware zoals Helmet.
Voorbeeld met Helmet:
const express = require('express');
const helmet = require('helmet');
const app = express();
app.use(helmet());
// Pas CSP aan indien nodig
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.example.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:"],
reportUri: '/csp-report'
},
}));
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server luistert op poort 3000');
});
Cloudflare
Met Cloudflare kunt u security headers instellen met behulp van hun Page Rules of Transform Rules.
Uw Security Headers Testen
Na het implementeren van security headers is het cruciaal om ze te testen om ervoor te zorgen dat ze correct werken. Verschillende online tools kunnen u helpen de security headers van uw website te analyseren:
- SecurityHeaders.com: Een eenvoudige en effectieve tool voor het analyseren van security headers.
- Mozilla Observatory: Een uitgebreide tool voor het testen van websitebeveiliging, inclusief security headers.
- WebPageTest.org: Hiermee kunt u de HTTP-headers bekijken in de watervalgrafiek.
Conclusie
Frontend security headers, met name Content Security Policy (CSP), zijn essentieel voor het beschermen van webapplicaties tegen diverse aanvallen en het verbeteren van de gebruikersveiligheid. Door deze headers zorgvuldig te implementeren en te onderhouden, kunt u het risico op XSS, clickjacking en andere beveiligingskwetsbaarheden aanzienlijk verminderen. Onthoud dat u moet beginnen met een alleen-rapporteren-beleid, de schendingsrapporten moet analyseren, het beleid moet verfijnen en vervolgens moet overschakelen naar de afdwingmodus. Monitor en update uw security headers regelmatig om uw website veilig te houden naarmate deze evolueert en er nieuwe bedreigingen opduiken.
Door een proactieve benadering van frontend-beveiliging te hanteren, kunt u veiligere en betrouwbaardere webapplicaties bouwen die uw gebruikers en uw bedrijf beschermen.